use lavender::{*};
use lavender::db::query_statement::prelude::*;


#[test]
fn query_where(){
   
}

#[test]
fn data_key_value(){


}

macro_rules! test_demo_query_item {
    ($f:tt $v:tt) => {
        println!("f {} v {} ",stringify!($f),stringify!($v));
    };
}

macro_rules! test_demo_query_items {
    ($( { $($item:tt)+ } );+) => {
        $(
            //println!("tt {} ",stringify!($($item)+));
            test_demo_query_item!($($item)+);
        )+        
    };
}
#[test]
fn test_items(){
    test_demo_query_items!( {"id" 8};{"age" 16});
}

macro_rules! blocks {
    ($($match:block)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}

macro_rules! expressions {
    ($($match:expr)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}

macro_rules! idents {
    ($($match:ident)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}

macro_rules! items {
    ($($match:item)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}
macro_rules! lifetimes {
    ($($match:lifetime)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}

macro_rules! literals {
    ($($match:literal)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}

macro_rules! metas {
    ($($match:meta)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}

macro_rules! patterns {
    (pat: $pat:pat) => {
        println!("pat: {}", stringify!($pat));
    };
    (pat_param: $($pat:pat_param)|+) => {
        $( println!("pat_param: {}", stringify!($pat)); )+
    };
    ($($match:pat)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}

macro_rules! paths {
    ($($match:path)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}

macro_rules! statements {
    ($($match:stmt)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}

macro_rules! visibilities {
    //         ∨~~注意这个逗号，`vis` 分类符自身不会匹配到逗号
    ($($match:vis,)*) => {
        $(
            println!("{}",stringify!($match));
        )+
    };
}

#[test]
fn test_block_macro(){
    println!("test blocks");
    blocks! {
        {}
        {
            let zig;
            let a = vec![1234];
            a
        }
        { 2 }
    }

    println!("test expressions");
    expressions! {
        "literal"
        funcall()
        future.await
        break 'foo bar
    }

    println!("test idents");
    idents! {
        // _ <- `_` 不是标识符，而是一种模式
        foo
        async
        O_________O
        _____O_____
    }

    println!("test items");
    items! {
        struct Foo;
        enum Bar {
            Baz
        }
        impl Foo {}
        /*...*/
    }
    
    println!("test lifetimes");
    lifetimes! {
        'static
        'shiv
        '_
    }

    println!("test literals");
    literals! {
        -1
        "hello world"
        2.3
        b'b'
        true
    }


    println!("test metas");
    metas! {
        ASimplePath
        super::man
        path = "home"
        foo(bar)
    }

    println!("test patterns");
    patterns! {
        "literal"
        _
        0..5
        ref mut PatternsAreNice
        0 | 1 | 2 | 3 
    }

    println!("test pat_param");
    patterns! {
        pat: 0 | 1 | 2 | 3
     }
     patterns! {
        pat_param: 0 | 1 | 2 | 3
     }

     println!("test paths");
     paths! {
        ASimplePath
        ::A::B::C::D
        G::<eneri>::C
        FnMut(u32) -> ()
    }

    println!("test statements");
    statements! {
        struct Foo;
        fn foo() {}
        let zig = 3
        let zig = 3;
        3
        3;
        if true {} else {}
        {}
    }

    println!("test visibilities");
    visibilities! {
        , // 没有 vis 也行，因为 $vis 隐式包含 `?` 的情况
        pub,
        pub(crate),
        pub(in super),
        pub(in some_path),
    }

}


pub fn test_literal(name:&str,value:&str){
    println!("call literal with \n`{}` = '{}'",name,value);
}

pub fn test_no_literal(name:&str,value:&str){
    println!("call no literal with \n`{}` = '{}'",name,value);
}

macro_rules! test_tt {
    (@inner $col:tt literal $val:tt) => {
        {
            test_literal($col,$val)
        }        
    };
    (@inner $col:tt literal $($ext:tt)+) => {
        {
            test_literal($col,$($ext)+)
        }        
    };
    (@inner $col:tt $val:tt) => {
        {
            test_no_literal($col,$val)
        }        
    };
    (@inner $col:tt $($ext:tt)+) => {
        {
            test_no_literal($col,$($ext)+)
        }        
    };
    ($( { $($item:tt)+ } ),+ ) => {
        { 
            $(
                test_tt!(@inner $($item)+);
            )+;
        }
    };
}

#[test]
fn test_concat_tt(){
    let code1 = ("600895","张江高科");
    let code2 = ("000001","上证指数");
    let code3 = ("399001","深证成指");
    test_tt!( {"code" code1.0},{"name" literal code1.1},
        {"code" code2.0},{"name" literal code2.1},
        {"code" code3.0},{"name" literal code3.1},
        {"id" "10010"}
    );
}